package com.cps116.friendstracker;

//
///*	List<Overlay> mapOverlays = mapView.getOverlays();
//	Drawable drawable = this.getResources().getDrawable(
//			R.drawable.androidmarker);
//	FriendFinderOverlay itemizedoverlay = new FriendFinderOverlay(drawable,
//			this);
//
//	itemizedoverlay.addOverlay(overlayitem);
//	mapOverlays.add(itemizedoverlay);*/


//	LinearLayout linearLayout;
//	GeoPoint point = new GeoPoint(19240000, -99120000);
//	OverlayItem overlayitem = new OverlayItem(point, "Hola, Mundo!",
//			"I'm in Mexico City!");


import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;

import com.cps116.parcelables.Coordinate;
import com.cps116.parcelables.LocationTraceList;
import com.cps116.parcelables.MapParcelable;
import com.cps116.parcelables.MapParcelableData;
import com.cps116.resource.HttpResponseDecoder;
import com.easy.facebook.android.apicall.FQL;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;
import com.google.android.maps.Projection;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Window;


public class FriendsFinderMapActivity extends MapActivity{

	private MapController mapControl;
	private MapView mapView;
	private List<Overlay> mapOverlays;
	private Projection projection;

	private IntentFilter friendsLocationIntentFilter;
	private FriendsLocationUpdateReceiver friendsLocationReceiver;


	//these are information for updating each individual overlay
	private Map<String, MapPathOverlay> userToOverlay;
	//	private Map<String, Long> userToUpdateTime; 
	private long groupUpdateTime;			//we simply want to update everyone at one time instead of having individual update time..
	private boolean needLiveUpdate; 		//this tells us whether we even need 


	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE); 	//Suppress title bar for more space 
		setContentView(R.layout.map_activity);

		//set up the mapview
		mapView = (MapView) findViewById(R.id.mapview);
		mapView.setBuiltInZoomControls(true);
		mapView.setTraffic(false);
		mapView.setBuiltInZoomControls(true);   // Set android:clickable=true in main.xml

		int maxZoom = mapView.getMaxZoomLevel();
		int initZoom = maxZoom-10;

		mapControl = mapView.getController();
		mapControl.setZoom(initZoom);

		mapOverlays = mapView.getOverlays();

		//get the intent's parcelable here
		MapParcelable mapOperator = getIntent().getParcelableExtra("overlays");
		Log.d("FriendsFinderMapActivity", "getting the parcelable object");

		if (mapOperator == null) 
		{
			new RetreiveMyLocation(this).execute("");
		}
		else {
			//here's where you are setting up the layouts...
			mapOperator.operateOnMapActivity(this);

			//set the update time...
			groupUpdateTime = getIntent().getLongExtra("update_time", 0);
			needLiveUpdate = getIntent().getBooleanExtra("need_to_update", false);

			if(needLiveUpdate && groupUpdateTime > 0){
				//we want to start the service right now...
				//start the service...
				((FriendsTrackerApplication)getApplication()).startNewFriendsLocationUpdateServiceInterva(this, groupUpdateTime);


				//set up the filter for listener...
				friendsLocationIntentFilter = new IntentFilter("com.cps116.FRIENDS_LOCATION_UPDATE");
				friendsLocationReceiver = new FriendsLocationUpdateReceiver(this);
				registerReceiver(friendsLocationReceiver, friendsLocationIntentFilter);   

			}
		}


		//TODO: ideally you want to get the user's overlay and set that as the top view...but 
		//we will just get the first element and set that 
		//TODO: set the alpha transparency value to almost fully transparent..so you can see overlaying path;
		//TOOD: start the service for calling 
		// by default, you start user services...        

	}


	@Override
	protected void onPause() {
		super.onPause();

		//pause whatever broadcast that we are listening to...
		//there could be multiple services that are broadcasted
		((FriendsTrackerApplication)getApplication()).terminateLiveFriendsUpdateService(this);
	}


	@Override
	protected void onResume() {
		super.onResume();

		//start whatever broadcast we are listening to...
		//this is where we listen for updates...
		((FriendsTrackerApplication)getApplication()).startNewFriendsLocationUpdateServiceInterva(this, groupUpdateTime);
	}


	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}




	//TO CHECK: check here for correctness!
	public void addOverlay(MapPathOverlay overlay, String userName, String userId, boolean isUpdating)
	{
		if (mapOverlays == null)
			mapOverlays = mapView.getOverlays();

		//add the new overlay
		mapOverlays.add(overlay);

		// there is no need to record username if is not updating..
		//we need to get the overlay later for update...
		if(isUpdating)
		{
			if (userToOverlay == null)
				userToOverlay =  new HashMap<String, MapPathOverlay>();

			userToOverlay.put(userId, overlay);

			//			if (userToUpdateTime == null)
			//				userToUpdateTime = new HashMap<String, Long>();
			//
			//			userToUpdateTime.put(userId, updateTimeMillis);
		}
	}

	/**
	 * TODO: we have to debug this class...
	 *
	 */
	private class FriendsLocationUpdateReceiver extends BroadcastReceiver {

		FriendsFinderMapActivity friendsFinderMapActivity;

		public FriendsLocationUpdateReceiver(FriendsFinderMapActivity friendsFinderMapActivity) {
			this.friendsFinderMapActivity = friendsFinderMapActivity;
		}

		@Override
		public void onReceive(Context context, Intent intent) {

			Log.d("FriendsLocationUpdateReceiver", "calling onReceiver");

			//getting the new list...
			LocationTraceList newList = intent.getParcelableExtra("live_update_coordinates");

			for(MapParcelableData mapUpdate: newList.getDataList())
			{
				String userId = mapUpdate.getUserId();

				//we don't bother with data for which an overlay does not exist in the first place...
				if(friendsFinderMapActivity.overlayExistsForUserId(userId))
				{
					MapPathOverlay overlay =  friendsFinderMapActivity.getOverlay(userId);
					for(Coordinate coord: mapUpdate.getCoords()) {
						int lat_micro = (int) (1e6 * coord.getLatCoord());
						int long_micro = (int) (1e6 * coord.getLongCoord());
						GeoPoint gp = new GeoPoint(lat_micro, long_micro);
						OverlayItem item = new OverlayItem(gp, "", "");
						//we simply want to add the element...
						overlay.addOverlay(item);
					}
				}
			}
		}
	}


	public boolean overlayExistsForUserId(String userId) {
		return userToOverlay.containsKey(userId);
	}

	public MapPathOverlay getOverlay(String userId)
	{	
		//BE CaREFUL...can return a null pointer exception
		return userToOverlay.get(userId);
	}


	//create the option menu 
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.friendstracker_menu, menu);
		return true;
	}

	//switching between different views

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {                              // 
		case R.id.menuOptionProfile:
			startActivity(new Intent(this, ProfileActivity.class));  // 
			break;
		case R.id.menuOptionMap:
			startActivity(new Intent(this, FriendsFinderMapActivity.class));
			break;
		case R.id.menuOptionQuery:
			startActivity(new Intent(this, QueryActivity.class));
			break;
		case R.id.menuOptionLogOut:

			break;
		}

		return true;  // 
	}


	//THE GETTER'S and the SETTER's

	public List<Overlay> getMapOverlays() {
		return mapOverlays;
	}


	public void setMapOverlays(List<Overlay> mapOverlays) {
		this.mapOverlays = mapOverlays;
	}



	public Projection getProjection() {
		return projection;
	}


	public void setProjection(Projection projection) {
		this.projection = projection;
	}



	public MapController getMapControl() {
		return mapControl;
	}


	private class RetreiveMyLocation extends AsyncTask<String, String, GeoPoint>
	{
		FriendsFinderMapActivity mapActivity;
		
		RetreiveMyLocation(FriendsFinderMapActivity m)
		{
			mapActivity = m;
		}
		

		@Override
		protected GeoPoint doInBackground(String... arg0)
		{
			HttpClient httpclient = new DefaultHttpClient();
			HttpPost httppost = new HttpPost("http://dbcourse.cs.duke.edu/tnd6/FFQueries/pulllastlocationinfo.php");

			String myUID = ((FriendsTrackerApplication) getApplication()).getFacebookUserId();

			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1);
			nameValuePairs.add(new BasicNameValuePair("userid", myUID));
			
			try 
			{
				httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
				HttpResponse response = httpclient.execute(httppost);
				String locationsString = HttpResponseDecoder.getResponseBody(response);
				
				Log.d("LOCATIONSSTRING", locationsString);

				if(! locationsString.equals(""));
				{
					//user_id;query_time;lat;long;road;
					Pattern coordsPattern = Pattern.compile("(.+?);(.+?);(.+?);(.+?);(.+?)");
					Matcher coordsMatcher = coordsPattern.matcher(locationsString);

					if(coordsMatcher.find())
					{
						Log.d("COORDS", coordsMatcher.group(3) + "," + coordsMatcher.group(4));
						
						int lat_micro = (int) (1e6 * Double.parseDouble(coordsMatcher.group(4)));
						int long_micro = (int) (1e6 * Double.parseDouble(coordsMatcher.group(3)));
						GeoPoint gp = new GeoPoint(lat_micro, long_micro);
						return gp;
					}

					return null;
				}
				
			}
			catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}



			return null;
		}

		@Override
		protected void onPostExecute(GeoPoint result) {
			super.onPostExecute(result);			
			
			Drawable icon = mapActivity.getResources().getDrawable(R.drawable.flag_1);
			MapPathOverlay overlay = new MapPathOverlay(icon, mapActivity);
			
			OverlayItem item = new OverlayItem(result, "", "");
			overlay.addOverlay(item);
			mapActivity.getMapOverlays().add(overlay);
		}

		@Override
		protected void onPreExecute() {
			// TODO Auto-generated method stub
			super.onPreExecute();
		}

	}



}
